import axios from 'axios'
import store from '../store'
import { ResponseCode } from '@/config/constants'
import Settings, { requestTimeout } from '@/config/settings'
import { Message } from 'element-ui'
import { getToken } from '@/utils/auth'
import { toLoginCenter } from '@/permission/auth'
import { sm2 } from 'sm-crypto'
// 请求参数加密处理
// import { aesUtil, rsaUtil, servePublicKey, privateKey } from '@/utils/encryption.js'
// 是否开启加密
const isEncryption = window.api_source.isEncryption === 'true'

const Codes = ResponseCode
const TokenKey = Settings.tokenKey
const requestMethods = ['put', 'post', 'patch']

// 递归过滤空值数据，其中空字符串需要特殊处理
// 空字符串置为null，不然后端查询接口查询不对
function filterNull(params) {
    if (params) {
        for (const key in params) {
            if (
                params[key] === '' ||
                params[key] === undefined
            ) {
                params[key] = null
            }
            if (params[key] instanceof Object) {
                filterNull(params[key])
            }
        }
    }
}

// 设置默认请求类型
axios.defaults.headers.post['Content-Type'] = 'application/json;charset=UTF-8'
const request = axios.create({
    // eslint-disable-next-line no-undef
    baseURL: api_source.url,
    timeout: requestTimeout,
})

let customContentType = null
request.interceptors.request.use(
    config => {
        if (config.method === 'get') {
            filterNull(config.params)
        }
        if (requestMethods.includes(config.method)) {
            // 如果是包含'saveOrUpdate'或'save'的是更新操作，不做处理，防止情空某项时不生效
            if (!config.url.includes('saveOrUpdate') && !config.url.includes('save')) {
                filterNull(config.data)
            }
        }
        const headers = config.headers || {}
        const token = getToken()
        if (token !== undefined) {
            headers[TokenKey] = token
        } else {
            headers[TokenKey] = 'Bearer token'
        }

        // headers['content-type']只有上传文件单独配置了该参数，有值则不走加密
        customContentType = headers['content-type']

        if (isEncryption && !customContentType) {
            headers['encryption-sign'] = 'YES'
            // const sm2 = require('sm-crypto').sm2
            const publicKey = `045a4c046531bf4909f7dd022ff27836a7483d131d64ec5a8ebd2af6bc18b07a50e9d9e90bf93051bc5c2b834f2ecaf14340e2ff4de8f833a857251d45d97e1256`
            const sm2Data = sm2.doEncrypt(JSON.stringify(config.data), publicKey, 1)
            config.data = encodeURIComponent(sm2Data)
        }
        return config
    },
    error => {
        return Promise.reject(error)
    }
)

const redirectLoginCode = [
    Codes.noPermission,
    Codes.appFreeze,
    Codes.tokenExpire,
    Codes.accountAbnormal,
    Codes.tokenNotExist
]

request.interceptors.response.use(
    response => {
        // 判断已经弹出的错误弹框数量是否为0
        const noErrorInfo = document.getElementsByClassName('el-message--error').length === 0

        const info = response.data || {}
        if (response.status === Codes.httpSuccess) {
            // 解密
            // if (isEncryption && !customContentType) {
            //     // 获取headers里的aeskey解码后解密
            //     // 注意：由于底层问题，后端在header里返回的字段名微信小程序里保留大写，Chrome里转成了小写
            //     const key = rsaUtil.decrypt(decodeURIComponent(response.headers['aes-key']), privateKey)
            //     // 把数据解码后用解密后的key解密，拿到正确数据
            //     info = aesUtil.decrypt(decodeURIComponent(info), key)
            // }
            const { code, message, data } = info
            // 如果返回200或者203，都是请求成功
            if (code === Codes.success || code === Codes.noData) {
                return Promise.resolve(data)
            } else {
                // 存在下面异常情况时，统一1.5s后跳转到登录页
                if (redirectLoginCode.includes(code)) {
                    noErrorInfo && Message({
                        message,
                        type: 'error',
                        duration: 1500,
                        onClose: () => {
                            store.dispatch('user/resetToken').then(() => {
                                toLoginCenter(false, true)
                            })
                        }
                    })
                } else {
                    // 其他异常code弹出后端返回的错误提示
                    noErrorInfo && Message.error(message)
                }
                // else if (code === Codes.serveError) {
                //     // 业务层500错误时，统一报错提示
                //     // 多条接口报错时，只弹出一个弹框
                //     noErrorInfo && Message.error('服务器异常，请稍后再试!')
                // } 
                return Promise.reject({ message, data })
            }
        } else {
            const message = '服务器异常，请稍后再试!'
            noErrorInfo && Message.error(message)
            return Promise.reject({ message, data: info })
        }
    },
    error => {
        if (document.getElementsByClassName('el-message--error').length === 0) {
            Message.error('网络异常，请稍后再试!')
        }
        return Promise.reject({ message: error.message, data: error })
    }
)

export default request
